# -*- coding: utf-8 -*-
from chee.shortcuts import *
############################################################################
class Misc_Continent(object):
    __storm_table__ = "misc_continent"
    id = Int(primary=True)
    name = Unicode(default=u'')
class Misc_Country(object):
    __storm_table__ = "misc_country"
    id = Int(primary=True)
    name = Unicode(default=u'')
    continent_id = Int(default=0)
    continent = Reference(continent_id,Misc_Continent.id)
    order_word = Unicode(default=u'')
class Misc_Area(object):
    __storm_table__ = "misc_area"
    id = Int(primary=True)
    country_id = Int(default=0)
    name = Unicode(default=u'')
    order_word = Unicode(default=u'')
    fare_type = Int(default=0)
class Misc_City(object):
    __storm_table__ = "misc_city"
    id = Int(primary=True)
    area_id = Int(default=0)
    name = Unicode(default=u'')
    phone_code = Unicode(default=u'')
    order_word = Unicode(default=u'')
    fare_type = Int(default=0)
class User_Info(object):
    __storm_table__ = "user_info"
    id = Int(primary=True)
    name = Unicode(default=u'')
    password = Unicode(default=u'')
    salt = Unicode(default=u'')
    email = Unicode(default=u'')
    nick_name = Unicode(default=u'')
    gender = Int(default=0)
    area_id = Int(default=0)
    area = Reference(area_id,Misc_Area.id)
    level = Int(default=0)
    experience = Int(default=0)
    gold = Int(default=0) # game gold
    bean = Int(default=0) # rmb 
    created = DateTime(default=datetime.max)
    create_ip = Unicode(default=u'')
    city_id = Int(default=0)
    create_referer = Unicode(default=u'')
    login_ip = Unicode(default=u'')
    login_time = DateTime(default=datetime.max)
    login_amount = Int(default=1)
    status = Int(default=0)
    photo = Unicode(default=u'')
    signature = Unicode(default=u'')
    key = Unicode(default=u'')

    def get_extid(self):
        from chee.models.external import External_User
        ext_usr = store.find(External_User,External_User.user_id==self.id).fetchOne(cache,'user_item_%d_ext_id'%self.id,3600)
        extid = 0
        if ext_usr: extid = ext_usr.ext_id
        return extid
    def getUserType(self):
        return u'网站用户'
    def isAdmin(self):
        perms = self.getPerm_ids()
        if perms and len(perms) > 0: return True
        return False
    @classmethod
    def hasUser(cls, username):
        return bool(store.find(User_Info,User_Info.name == username).count())
    @classmethod
    def hasNickCount(cls, nick):
        return store.find(User_Info,User_Info.nick_name == nick).count()
    def getPerm_ids(self):
        from chee.models.user import User_Role,User_Info_Role,User_Role_Perm
        tbs = [User_Role_Perm,Join(User_Info_Role,User_Info_Role.role_id==User_Role_Perm.role_id)]
        perms = store.using(*tbs).find((User_Role_Perm.permission_id,User_Role_Perm.operation_id),User_Info_Role.user_id==self.id
                    ).fetchAll(cache,'user_item_%d_permids'%self.id,3600)
        return perms
    def hasNewMail(self):
        from chee.models.user import User_Mail
        count = store.find(Count(User_Mail.id),User_Mail.owner_id == self.id,User_Mail.to_id == self.id,
                User_Mail.is_read == 0).fetchOne(cache,'user_item_%d_flag_mail'%self.id,300)
        return count != 0
    def isMyFriend(self,friend_id):
        from chee.models.user import User_Friend
        return User_Friend.isFriend(self.id, friend_id)
    def login(self, request):
        """用户登录"""
        request.user = self
        self.login_ip = unicode(request.remote_addr,'utf-8')
        self.login_time = datetime.now()
        self.login_amount = self.login_amount + 1
        if not self.key: self.key = getRandKey();
        
        store.add(self)
        store.commit()
        request.user_id = self.id
    def setPassword(self, raw_password):
        """设置用户密码"""
        import random
        salt = get_hexdigest_ex('md5', str(random.random()),
                            str(random.random()))[:5]
        self.salt = unicode(salt)
        self.password = unicode(get_hexdigest_ex('md5', salt, raw_password))
    def checkPassword(self, raw_password):
        """检查密码与用户密码是否匹配
        Returns a boolean of whether the raw_password was correct. Handles
        encryption formats behind the scenes.
        """
        #return check_password(raw_password, self.password)
        # Backwards-compatibility check. Older passwords won't include the
        # algorithm or salt.
        if '$' not in self.password:
            is_correct = (self.password == 
                          get_hexdigest_ex('md5', self.salt, raw_password))
            if is_correct:
                # Convert the password to the new, more secure format.
                self.setPassword(raw_password)
                
                store.add(self)
                store.commit()
            return is_correct
        else:
            return check_password(raw_password, self.password)
    def getRoles(self):
        from chee.models.user import User_Role,User_Info_Role
        tbs = [User_Role,Join(User_Info_Role,User_Info_Role.role_id==User_Role.id)]
        return store.using(*tbs).find(User_Role,User_Info_Role.user_id==self.id).order_by(Asc(User_Role.id))
    @classmethod
    def addNew(cls,usrname,nick_name,email,request,usr_photo=u'',password=u'',user_type=-1):
        ''' 新增一个用户,主要用于合作伙伴的用户来访问时自动新建用户
                                方法返回用户ID, usrname必须是一个邮件地址,否则将不予添加
        ''' 
        # 首先检查是否存在该用户,如果存在则直接返回用户ID
        usr = store.find(User_Info,User_Info.name==usrname).one()
        if usr: 
            usr.login(request)
            if usr.email != email or usr.nick_name != nick_name or (usr_photo and usr.photo != usr_photo):
                usr.email = email; usr.nick_name = nick_name; usr.photo = usr_photo;
                store.add(usr); store.commit()
            return usr.id
        usr = User_Info()
        usr.name = usrname
        usr.nick_name = nick_name
        usr.email = email
        try:
            if user_type != -1: usr.user_type = user_type
            else: usr.user_type = 0
        except: pass
        if usr_photo: usr.photo = usr_photo
        usr.created = datetime.now()
        usr.area_id = 0
        # set referer if exists
        if request.cookies.has_key('referer'): usr.create_referer = request.cookies['referer']
        if not password:
            # 设定密码为临时密码
            # need md5_hash, as java script hashed password on client
            import md5
            upass = getRandKey(length=8)
            now_pass_hash = md5.new(upass).hexdigest()
            usr.setPassword(now_pass_hash)
        else:
            usr.setPassword(password)
        store.add(usr)
        store.commit()
        usr.login(request)
        return usr.id
        
class TableOp:
    def __init__(self, store):
        self.db = store

    def getTables(self):
        tables = []
        for table in self.db.execute('SHOW TABLES'):
            tables.append(table[0])
        return tables

    def dropTables(self):
        tables = [table[0] for table in self.db.execute('SHOW TABLES')]
        for table in tables:
            self.store.execute('drop table if exists %s' % table)

    def isTableExist(self, table_name):
        tables = self.getTables()
        if table_name in tables:
            return True
        else:
            return False 
        return False
    
    def createTable(self, sql):
        try:
            self.db.execute(sql)
        except Exception, e:
            return False
        return True
    
    def dropTable(self, tb_name):
        try:
            sql = 'DROP TABLE IF EXISTS `%s`;'%(tb_name)
            self.db.execute(sql)
        except Exception, e:
            return False
        return True
def get_hexdigest_ex(algorithm, salt, raw_password):
    """ 
    Returns a string of the hexdigest of the given plaintext password and salt
    using the given algorithm ('md5', 'sha1' or 'crypt').
    """
    raw_password, salt = str(raw_password), str(salt)
    if algorithm == 'crypt':
        try:
            import crypt
        except ImportError:
            raise ValueError('"crypt" password algorithm not supported in this environment')
        return crypt.crypt(raw_password, salt)
    # The rest of the supported algorithms are supported by hashlib, but
    # hashlib is only available in Python 2.5.
    try:
        import hashlib
    except ImportError:
        if algorithm == 'md5':
            import md5 
            return md5.new(raw_password + salt).hexdigest()
        elif algorithm == 'sha1':
            import sha 
            return sha.new(raw_password + salt).hexdigest()
    else:
        if algorithm == 'md5':
            return hashlib.md5(raw_password + salt).hexdigest()
        elif algorithm == 'sha1':
            return hashlib.sha1(raw_password + salt).hexdigest()
    raise ValueError("Got unknown password algorithm type in password.")
